/***********************************
BigInt
BigInt.cpp - Implementation file
Calculator for large integers.
CS 133 - Parallel Programming
Professor: Adam Kaplan
Due: 6/3/2011
Collaborators:
Ben Harounian
Justin Kiang
Akhil Rangaraj
************************************/
#include "BigInt.h"
using namespace std;



/***** Definitions *****/


/*** Constructors ***/

// Default Constructor
BigInt::BigInt()
{
    // Initialize private variables
    // Set 1 thread default
    numThreads = 1;

    // Clear container, create BigAssData element
  //  decimalContainer.clear();
    binaryContainer.clear();
    
    
   // decimalContainer.push_back("0");
    binaryContainer.push_back(0);
}// End default constructor


// Specific Constructor - Takes String
BigInt::BigInt(const std::string &str)
{
    // Call specific constructor
    *this = BigInt(str, 1);
}// End specific constructor


// Specific Constructor - Takes String and Number of Threads
/* USER HAS TO CHECK MAX_THREADS BEFORE SETTING PRIVATE VARIABLE */
BigInt::BigInt(const std::string &str, const int threads)
{
    // Initialize private variables
    string quotient = "";
    string binary = "";
    string transient = str;
    string remainder = "";
 //   decimalContainer.clear();
    binaryContainer.clear();
   //cout <<" inserting " << str<<endl; 
   while(strcmp(transient.c_str(),"0") && strcmp(transient.c_str(),"1")){
        
        remainder = divideBy2(transient,quotient);
        transient = quotient;
     
       binary = remainder+binary;
}
   //if(!strcmp(remainder.c_str(),"1"))
       binary = transient+binary;
	//cout << "Binary Str" <<binary<<endl;
    int binaryCounter = 0;
     const char* binaryCstr = binary.c_str();
     string tempBinary ="";
     while(*binaryCstr !='\0')
     {
          tempBinary += *(binaryCstr++);   //add binary digit to string
          binaryCounter++;
          if(binaryCounter ==16 || *(binaryCstr)=='\0')
              {
		
                  binaryCounter=0;
		//cout<<"hello " << tempBinary;
                  int herples=  (unsigned int) bitset<16>(tempBinary).to_ulong();
			//cout << " push back " << herples <<endl;
                  binaryContainer.push_back(herples);
                  tempBinary="";
              }
     }// End while
	//cout <<"hello2"<<endl;
    // Set numberof threads
    numThreads = threads;
/*	string str2 = string(str);
    string::reverse_iterator rit;
     string temp="";
         int digitCounter =0;
    for(rit = str2.rbegin(); rit< str2.rend(); rit++)
    {
            temp += *rit;
            digitCounter++;
             if(digitCounter ==5 || rit == str2.rend()-1)
                {
                    decimalContainer.push_back(string(temp.rbegin(), temp.rend()));
                    temp="";
                        digitCounter =0;
                }
    }*/
	
}// End specific constructor


// Copy Constructor
BigInt::BigInt(const BigInt &another)
{
    // Initialize private variables
   // decimalContainer = vector<string>(another.decimalContainer);
    binaryContainer = vector<int>(another.binaryContainer);
    // Set numberofThreads
    numThreads = another.numThreads;

}// End copy constructor


// Specific Constructor - Takes Integer
BigInt::BigInt(const int val)
{
    // Initialize private variables
    std::string temp = "";
    std::stringstream out;

    // Read val to stringstream, parse int
    out << val;
    temp = out.str();
	//cout << "INTEGER BIGINT: "<<temp<<endl;
    // Call specific constructor
    *this = BigInt(temp, 1);
}// End specific constructor





/*** Operators ***/

/* Arithmetic Operations */


// Operator+ Overloading
const BigInt BigInt::operator+ (const BigInt &right) const
{
    // Make a copy, add the right hand side, return
    return BigInt(*this) += right;
}// End operator+ overloading


// Operator* Overloading
const BigInt BigInt::operator* (const BigInt &right) const
{
    // Make a copy, multiply by the right hand side, return
    return BigInt(*this) *= right;
}// End operator* overloading


/* Bitwise Operations */


// Operator| Overloading
const BigInt BigInt::operator| (const BigInt &right) const
{
    // Make a copy, OR with the right hand side, return
    return BigInt(*this) |= right;
}// End operator| overloading


// Operator^ Overloading
const BigInt BigInt::operator^ (const BigInt &right) const
{
    // Make a copy, XOR with the right hand side, return
    return BigInt(*this) ^= right;
}// End operator^ overloading


// Operator& Overloading
const BigInt BigInt::operator& (const BigInt &right) const
{
    // Make a copy, AND with the right hand side, return
    return BigInt(*this) &= right;
}// End operator& overloading


// Operator! Overloading
/* PROBLEM WITH FLIPPING THE LAST SET OF BITS */
BigInt BigInt::operator! ()
{
    // Flip all the bits
    // Declare, initialize variables
    size_t size = this->binaryContainer.size();

    // Loop and flip bits in the bit array
    #pragma omp parallel num_threads(numThreads)
    {
	#pragma omp for
    	for (size_t i = 0; i < size; i++)
    	{	
       	 // Flip bits
        	this->binaryContainer[i] = !this->binaryContainer[i];

    	}// End for
    //we need to update the ddecimal representation
    }
    return *this;
}// End operator! overloading


/* Assignment Operations */


// Operator= Overloading
BigInt& BigInt::operator= (BigInt right)
{
    // Only allocate if two objects aren't equal
    if (this != &right)
    {
        // Declare, initialize variables


        // Assign numThreads
        numThreads = right.numThreads;
      // decimalContainer = vector<string>(right.decimalContainer);
           binaryContainer = vector<int>(right.binaryContainer);
}
    return *this;
}// End operator= overloading


/* Compound Assignment Operations */


// Operator+= Overloading
    BigInt& BigInt::operator+= (const BigInt &right)
{
    // Declare, initialize variables
    size_t this_size = this->binaryContainer.size();
    size_t right_size = right.binaryContainer.size();
//if(this_size ==0 || right_size==0)
	//cout <<"asdjashd";
    // Find out which size is larger
    bool this_is_bigger = (this_size > right_size);
    bool right_is_bigger = (right_size > this_size);
    size_t container_size = std::max(this_size, right_size);
    size_t loop_size = std::min(this_size, right_size);
size_t diff_size = container_size - loop_size;
//cout <<"DIFF SIZE" <<diff_size<<endl;
    BigInt result;

	int* binaryArray = new int[container_size];
	bool* overflowArray= new bool[container_size];
	for (int i = 0; i < container_size; i++)
		overflowArray[i] = false;
	#pragma omp parallel num_threads(numThreads)
	{
		#pragma omp for 
		for (size_t i = 0; i < loop_size; i++)
		{
			std::bitset<16> thisInt;
			std::bitset<16>rightInt;
			if(this_is_bigger)
				thisInt =bitset<16>(this->binaryContainer[i+diff_size]);
			else
				thisInt =bitset<16>(this->binaryContainer[i]);
			if(right_is_bigger)
				rightInt =bitset<16>(right.binaryContainer[i+diff_size]);
			else
				rightInt = bitset<16>(right.binaryContainer[i]);
			std::bitset<16> result2; 
			__addHelper(thisInt, rightInt, &result2, &overflowArray[i]);
			binaryArray[i] = (int)result2.to_ulong();
			//cout << "binaryArray " << binaryArray[i] << " i: " <<i<<endl;
		}
	}

	
	//step 2 of calculation (do remainders)
	
        if (this_is_bigger)
        {
            // ADD other values
            #pragma parallel num_threads(numThreads) 
	    {
            #pragma omp for
            for (size_t i = loop_size; i < container_size; i++)
            {
		std::bitset<16> thisInt(this->binaryContainer[i]);
   		std::bitset<16> tempArray;
		std::bitset<16> result2;
		tempArray.reset();
	//cout<<"THIS IS BIGGER"<<endl;
		__addHelper(thisInt,tempArray,&result2, &overflowArray[i]);
			binaryArray[i] = (int)result2.to_ulong();
	    }
            }
        }// End if
    
        // Copy the rest from right
        else if (right_is_bigger)
        {
            #pragma parallel num_threads(numThreads) 
	    {
            #pragma omp for
            for (size_t i = loop_size; i < container_size; i++)
            {
		std::bitset<16> thisInt(right.binaryContainer[i]);
   		std::bitset<16> tempArray;
		std::bitset<16> result2;
		tempArray.reset();
		//cout <<"this int " << thisInt.to_ulong() << " i: "<<i<< endl;
		__addHelper(thisInt,tempArray,&result2, &overflowArray[i]);
			binaryArray[i] = (int)result2.to_ulong();
			//cout <<"BINARY ARRAY RIGHT BIGGER:  " << binaryArray[i]<<endl;
	    }
            }
	}
    
    
       #pragma omp single
        {
	bool carryout = false;
            // Perform Step 2 Of Calculation
            size_t i;
            for ( i = 0; i < container_size; i++)
            {
                // Ignore first iteration
	carryout = false;
                if (i != 0)
                {
		//cout <<"inbound: "<<binaryArray[i]<<endl;
		std::bitset<16> inbound(binaryArray[i]);
		std::bitset<16> one(1);
		std::bitset<16> result2(0);
		if(overflowArray[i-1]) {
			 __addHelper(inbound, one, &result2, &carryout);
			overflowArray[i] |= carryout;}
			this->binaryContainer.push_back((int)result2.to_ulong());	
		//cout <<" RESULT " << result2.to_ulong()<< " I: "<<i<<endl;
		}
		else
		{
			//cout << " WRITING " << binaryArray[i]  << "TO CONTAINER" <<endl;
			binaryContainer[i] = binaryArray[i];
		}
	
	    }
	    if(overflowArray[--i])
	    {
			//cout << " WRITING A ONE TO CONTAINER" <<endl;
		this->binaryContainer.push_back(1);
	    }
	}
            


    return *this;
}// End operator+= overloading


// Operator*= Overloading
/*BigInt& BigInt::operator*= (const BigInt &right)
{
    // TO DO:
    // My thoughts:
    // For the following calculation     1246
    // we can make a BigInt for      x2378
    // the result of each calculation, and
    // store these in an array of BigInts
    // ie: array[0] would have 1246 * 8
    // ie: array[1] would have 1246 * 7 * 10
    // ie: array[2] would have 1246 * 3 * 100
    // IE: array[i] would have TOP_NUMBER * ith digit in BOTTOM_NUMBER * 10^i
    // We can do these in parallel, and then add up (operator+) the resulting
    // BigInts in the array in parallel as well.
    // BAM!


    // Algorithm
    // We're going to assume that this is below and right is above
    // Take the size of this and create a new BigInt for each digit in this
    // Make an array of BigInts with the length equal to the size of this
    // Multiply each digit in this by all of right and by a power of 10 (addition in for loop)
    // Add each element in the array together
    // Return the result

    // Declare, initialize variables
    std::string arr_string = this->toString();
    size_t arr_siz = arr_string.size();
    BigInt* arr = new BigInt[arr_siz];
    BigInt* result_arr = new BigInt[arr_siz];
    BigInt result;
    std::string temp;
    //std:://cout << "Arr_siz = " << arr_siz << "\n";

    //std:://cout << "ARR_STRING is this: +" << arr_string << "+\n";


    // Loop and populate the array of BigInts
    // the string "12345" will be [5, 4, 3, 2, 1]
    //std:://cout << "****************FOR LOOP 1****************\n";
    for (int i = arr_siz - 1; i >= 0; i--)
    {
        //std:://cout << "i = " << i << " and arr_siz - i - 1 = " << (arr_siz - i - 1) << " and arr_string[" << i << "] is " << arr_string[i] << "\n";
        // Create BigInt objects
        temp = arr_string[i];
        arr[arr_siz - i - 1] = BigInt(atoi(temp.c_str()));
        //std:://cout << "The object at " << arr_siz - i - 1 << " has a value of " << arr[arr_siz - i - 1].toString() << "\n";
        result_arr[i] = BigInt(0);
    }// End for
    //std:://cout << "****************END LOOP 1****************\n";

    // Loop and calculate the multiplication by doing a bunch of additions
    //std:://cout << "****************FOR LOOP 2****************\n";
           //can parallelize
           #pragma omp parallel for
    for (int i = 0; i < arr_siz; i++)
    {
        // Store number 5..4..3..2..1, multiply by 10^i
        int loop_num = atoi(arr[i].decimalContainer[0].c_str());
        loop_num *= (int) pow((double) 10, i);
	#pragma omp critical 
{
       std:://cout << "i is " << i << " and loop_num is " << arr[i].decimalContainer[0] << "*" << pow((double) 10, i) << " or " << loop_num << "\n";
        }
        // Calculate each individual multiplication problem
        #pragma omp parallel for 
        for (int j = 0; j < loop_num; j++)
        {
            // 5 * 10^0 * right = result_arr[0]
            // 4 * 10^1 * right = result_arr[1]
            result_arr[i] += right;
            //std:://cout << "This is the current result after adding right: " << result_arr[i].toString() << "\n";
        }// End for
    }// End for
    std:://cout << "****************END LOOP 2****************\n";

    // Loop through and add each element in the result_arr to result
    for (int i = 0; i < arr_siz; i++)
    {
        result += result_arr[i];
    }// End for


    *this = result;
    return *this;
}// End operator*= overloading
*/

// Operator|= Overloading
BigInt& BigInt::operator|= (const BigInt &right)
{
    // Declare, initialize variables
    size_t this_size = this->binaryContainer.size();
    size_t right_size = right.binaryContainer.size();

    // Find out which size is larger
    bool this_is_bigger = this_size > right_size;
    size_t container_size = (this_size > right_size) ? this_size : right_size;
    size_t loop_size = (this_size < right_size) ? this_size : right_size;

    // Variables for iterating
    int i = 0;
    std::stringstream out;
    BigInt result;
    result.binaryContainer.resize(container_size);

    // OR the values that both share
    #pragma omp parallel for
    for (i=0; i < loop_size; i++)
    {
        result.binaryContainer[i] = this->binaryContainer[i] | right.binaryContainer[i];
    }// End for

    // OR the extra values
    // Copy the rest from this
    if (this_is_bigger)
    {
        #pragma omp parallel for
        for (i = loop_size; i < this_size; i++)
        {
            result.binaryContainer[i] = this->binaryContainer[i];
        }// End for
    }// End if

    // Copy the rest from right
    else
    {
        for (i = loop_size; i < right_size; i++)
        {
            result.binaryContainer[i] = right.binaryContainer[i];
        }// End for
    }// End else    

    *this = result;
    return *this;
}// End operator|= overloading


// Operator^= Overloading
BigInt& BigInt::operator^= (const BigInt &right)
{
    // Declare, initialize variables
    size_t this_size = this->binaryContainer.size();
    size_t right_size = right.binaryContainer.size();

    // Find out which size is larger
    bool this_is_bigger = this_size > right_size;
    size_t container_size = (this_size > right_size) ? this_size : right_size;
    size_t loop_size = (this_size < right_size) ? this_size : right_size;

    // Variables for iterating
    int i = 0;
    std::stringstream out;
    BigInt result;
    result.binaryContainer.resize(container_size);

    // XOR the values that both share
    #pragma omp parallel for
    for (i=0; i < loop_size; i++)
    {
        result.binaryContainer[i] = this->binaryContainer[i] ^ right.binaryContainer[i];
    }// End for

    // XOR the extra values
    // Copy the rest from this
    
    if (this_is_bigger)
    {
    #pragma omp parallel for
        for (i = loop_size; i < this_size; i++)
        {
            result.binaryContainer[i] = this->binaryContainer[i];
        }// End for
    }// End if

    // Copy the rest from right
    else
    {
        #pragma omp parallel for
        for (i = loop_size; i < right_size; i++)
        {
            result.binaryContainer[i] = right.binaryContainer[i];
        }// End for
    }// End else    

    *this = result;
    return *this;
}// End operator^= overloading


// Operator&= Overloading
BigInt& BigInt::operator&= (const BigInt &right)
{
    // Declare, initialize variables
    size_t this_size = this->binaryContainer.size();
    size_t right_size = right.binaryContainer.size();
    // Find out which size is larger
    bool this_is_bigger = this_size > right_size;
    size_t container_size = (this_size > right_size) ? this_size : right_size;
    size_t loop_size = (this_size < right_size) ? this_size : right_size;

    // Variables for iterating
    size_t i = 0;
    std::stringstream out;
    BigInt result;
    result.binaryContainer.resize(container_size);

    // AND the values that both share
    #pragma omp parallel for
    for (i=0; i < loop_size; i++)
    {
        result.binaryContainer[i] = this->binaryContainer[i] & right.binaryContainer[i];
    }// End for

    // AND the extra values
    // Copy the rest from this
    if (this_is_bigger)
    {
        #pragma omp parallel for
        for (i = loop_size; i < this_size; i++)
        {
            result.binaryContainer[i] = this->binaryContainer[i];
        }// End for
    }// End if

    // Copy the rest from right
    else
    {
        #pragma omp parallel for
        for (i = loop_size; i < right_size; i++)
        {
            result.binaryContainer[i] = right.binaryContainer[i];
        }// End for
    }// End else    

    *this = result;
    return *this;
}// End operator&= overloading


/* Comparison Operations */


// Operator== Overloading
bool BigInt::operator== (BigInt &right) const
{
    // Declare, initialize variables
    size_t size = right.binaryContainer.size();
    bool match = true;
    // False if containers don't match size
    if (this->binaryContainer.size() != size)
    {
        match = false;
    }// End if
    if(!match) return match;
    // Loop and check each value
       
    #pragma omp parallel for 
    for (int i = 0; i < size; i++)
    {
        // They don't match
        if (this->binaryContainer[i]!= right.binaryContainer[i])
        {
            match = false;
        }// End if
    }// End for
    
    if(!match) return match;
    size = right.decimalContainer.size();
    if(this->decimalContainer.size() != size){
        match = false;
    }
    if(!match) return match;
    #pragma omp parallel for
    for (size_t i=0; i<size; i++){
        if(strcmp(this->decimalContainer[i].c_str(), right.decimalContainer[i].c_str()))
        {
            match = false;
        }
    }
    // They match
    return match;
}// End operator== overloading



/*** Helpers ***/

// To String Function
std::string BigInt::toString()
{
        vector<int> quotient2 (binaryContainer.rbegin(), binaryContainer.rend());
//	for (int i = 0; i < quotient2.size(); i++)
		//cout << " "<<quotient2[i];
	//cout <<endl;
	//cout <<"BINARY CONTAINER"<<endl;
//	for (int i =0; i < binaryContainer.size();i++)
		//cout << " "<<binaryContainer[i];
	//cout <<endl;
    std::string result = BinToStr(quotient2, "");
    return result;
}
/*    // Declare, initialize variables
    std::string result = "";
    size_t size = this->decimalContainer.size();

    #pragma omp parallel for
    for (size_t i = 0; i < size; i++)
    {
        //result += this->container[i].data;
        // As long as you still have data to print
        if (i != size - 1)
        {
            // Fix problem with 5 0's
            if (this->decimalContainer[i] == "0")
            {
                // Change to 5 0's
                this->decimalContainer[i] = "00000";
            }// End if
        }// End if
	#pragma omp critical 
	{
        result.insert(BEGINNING, this->decimalContainer[i]);
	}
    }// End for

    return result;
}// End toString function
*/

string BigInt::divideBy2(string number, string & quotient){
        int x = 0;
        quotient = "";
        const char* derp = number.c_str();
        string thisDigit = "";
        bool begin = true;
        while(*derp != '\0') {
                thisDigit= string(1,*derp);
                if(x != 0){
                        x += atoi(thisDigit.c_str());
                        stringstream s;
                        double temp = x/2;
                        s << floor(temp);
                        quotient += s.str();
                        x = (x%2)*10;
                        begin = false;
                }
                else{
                        if(atoi(thisDigit.c_str())<2){
                                if(!begin){
                                    quotient += "0";
                                }
                                x += 10*atoi(thisDigit.c_str());
                        }
                        else{

                                stringstream s;
                                double value = atoi(thisDigit.c_str())/2;
                                s << (int) floor(value);
                                quotient += s.str();
                                begin = false;
                                if(atoi(thisDigit.c_str())%2){
                                    x = 10;
                                }
                        }
                }
                 derp++;
        }
        return (atoi(thisDigit.c_str())%2)?"1":"0";
}



string BigInt::BinToStr(vector<int> quotient,string str)
{
 vector<int> quotient2;
        if(quotient.size() == 1)
        {
                stringstream a;
                a << quotient[0];
                string temp = a.str();
                return temp+str;
        }
        int top = quotient[0];
        //cout << " TOP " <<top<<endl;
        size_t i =0;// quotient.size();
        int remainder = 0;

        string temp = "";
        while(i < quotient.size())
        {
        int dividend =  top/10;
        remainder= top%10;
        if(dividend !=0)
        quotient2.push_back(dividend);
        //cout << top << " "<<dividend<<" "<<remainder<<" "<<endl ;
        top = quotient[++i];
        top += (remainder?remainder:1)*65536;
        }
        stringstream s;
        s << remainder;
        temp=s.str();
        return BinToStr(quotient2, temp+str);


}

void BigInt::__addHelper(std::bitset<16> left, std::bitset<16> right, std::bitset<16> *result, bool *overflow)
{
	std::bitset<16+1> value_a;
	std::bitset<16+1> value_b;
	std::bitset<16+1> sum;
	std::bitset<16+1> carry;
	
	#pragma omp parallel num_threads(numThreads)
	{
		#pragma omp for
		for (int i =0; i < 16 ; i++)
		{
			value_a[15-i] = left[15-i];
			value_b[15-i] = right[15-i];
		}
	}
	
	sum = value_a ^ value_b;
	carry=value_a & value_b;
	
	while(carry.any())
	{
		carry <<=1;
		value_a = sum;
		value_b = carry;
		sum = value_a ^ value_b;
		carry=value_a & value_b;
	}
	
//	carry.reset();
//	carry[16] = (*overflow);
//	sum = (sum^carry)| ((sum&carry) <<1);
	
	
	#pragma omp parallel num_threads(numThreads)
	{
		#pragma omp for
		for(int i = 0; i < 16; i++)
			(*result)[i] = sum[i];
	}
	*overflow  = sum[16];
}
void leftTrim(std::string& src, char chr)
{
  std::string::size_type pos =  src.find_first_not_of(chr,0);
  if(pos > 0)
    src.erase(0,pos);
}
BigInt& BigInt::operator*= (const BigInt &right){
        size_t rightSize = right.binaryContainer.size();
        size_t thisSize = this->binaryContainer.size();
        string rightStr = "";
        string thisStr = "";
        size_t rightBinarySize = 0;
        size_t thisBinarySize = 0;
        for(size_t i = 0; i < rightSize; i++){
                string quotient = "";
                stringstream s;
                s.str("");
                s << right.binaryContainer[i];
                //cout << "RIGHT CONTAINER [i] = " << right.binaryContainer[i]<<endl;

                string transient = s.str();
                string remainder = "";
                string temp = "";
                while(strcmp(transient.c_str(),"0") && strcmp(transient.c_str(),"1")){
                        remainder = divideBy2(transient,quotient);
                        transient = quotient;
                        temp = remainder+temp;
                }
                //if(!strcmp(remainder.c_str(),"1"))
                        temp = transient+temp;
                rightStr += temp;
                rightBinarySize += temp.size();
        }
        for(size_t i = 0; i < thisSize; i++){
                string quotient = "";
                stringstream s;
                s.str("");
                s << this->binaryContainer[i];
                string transient = s.str();
                string remainder = "";
                string temp = "";
                while(strcmp(transient.c_str(),"0") && strcmp(transient.c_str(),"1")){
                        remainder = divideBy2(transient,quotient);
                        transient = quotient;
                        temp = remainder+temp;
                }
                //if(!strcmp(remainder.c_str(),"1"))
                        temp = transient+temp;
                thisStr += temp;
                thisBinarySize += temp.size();
        }
        string* workingArray = new string[rightBinarySize];

        for (size_t i = 0; i<rightBinarySize; i++){
                //cout << "c";
                workingArray[i] = "";
                for (size_t j=0; j<rightBinarySize+thisBinarySize; j++){
                        workingArray[i] += "0";
                }
        }

        for (size_t i=0; i<rightBinarySize; i++){
                //cout << "d";
                if(rightStr[i] == '0'){
                        for(size_t j=0; j<thisBinarySize; j++){
                                workingArray[i][j+i+1]='0';
                        }
                }else{
                        for(size_t j=0; j<thisBinarySize; j++){
                                workingArray[i][j+i+1]=(thisStr[j]=='1')?'1':'0';
                        }
                }
        }
        //cout << "RIGHT STR: "<<rightStr<<endl;
        //cout << "THIS STR : "<<thisStr<<endl;
        BigInt* result = new BigInt("0");
	//cout<< "RIGHT BINARY SIZE:" <<rightBinarySize<<endl;
        for (size_t i=0; i<rightBinarySize; i++){
                leftTrim(workingArray[i],'0');
cout<<"ITERATION: "<<i<<endl;
                if(workingArray[i].empty()) workingArray[i]="0";
                BigInt* temp = new BigInt("0",numThreads);
                temp->binaryContainer.clear();
                int binaryCounter = 0;
                const char* binaryCstr = workingArray[i].c_str();
                string tempBinary ="";
                //cout << workingArray[i];
                while(*binaryCstr !='\0')
                {
                        tempBinary += *(binaryCstr++);   //add binary digit to string
                        binaryCounter++;
                        if(binaryCounter ==16 || *(binaryCstr)=='\0')
                        {
                                binaryCounter=0;
                                int herples=  (int) bitset<16>(tempBinary).to_ulong();
                                temp->binaryContainer.push_back(herples);
                                //cout << "    " << herples << "    ";
                                tempBinary="";
                        }
                }
                //cout << "-----------------------------------------------" <<temp->toString() << endl;
		BigInt* temp2 = new BigInt(result->toString(),numThreads);
		*temp2+=*temp;
		delete result;
		result = new BigInt(temp2->toString(),numThreads);
                delete temp;
		delete temp2;
        }
        *this = *result;
        return *this;

}

